// 2DMapView.cpp : implementation file
//

#include "stdafx.h"
#include "TerrainEditor.h"
#include "TerrainEditorDoc.h"
#include "OpenGLView.h"
#include "2DMapView.h"
#include "PerlinNoiseDlg.h"
#include "OpenGLInfoDlg.h"
#include "gl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// C2DMapView

IMPLEMENT_DYNCREATE(C2DMapView, COpenGLView)

C2DMapView::C2DMapView()
{
	// Initialize variables

	m_bMouseLBDown = false;
	m_vDefaultCamPos.x = 10.0f;
	m_vDefaultCamPos.y = 10.0f;
}

C2DMapView::~C2DMapView()
{
}

BEGIN_MESSAGE_MAP(C2DMapView, COpenGLView)
	//{{AFX_MSG_MAP(C2DMapView)
	ON_COMMAND(ID_MENUITEM_PerlinNoise, OnMenuItemPerlinNoise)
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(ID_MENUITEM_OpenGLInfo, OnMenuItemOpenGLInfo)
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// C2DMapView drawing

/////////////////////////////////////////////////////////////////////////////
// C2DMapView diagnostics

#ifdef _DEBUG
void C2DMapView::AssertValid() const
{
	CView::AssertValid();
}

void C2DMapView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CTerrainEditorDoc* C2DMapView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTerrainEditorDoc)));
	return (CTerrainEditorDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// C2DMapView message handlers

void C2DMapView::VirtualOnCreate()
{
	// Clear background color to black

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	// Reset Z-Buffer value

	glClearDepth(1.0f);
}

void C2DMapView::VirtualOnDraw()
{
	// Grab a pointer to the doc

	CTerrainEditorDoc *pDoc = GetDocument();

	// Check to see if a terrain has been created

	if (pDoc->m_bTerrainDataExists == true)
	{
		if (pDoc->m_b2DNewTerrainGenerated == true)
		{
			m_MapTexture.CreateTextureFromImage(pDoc->m_Heightmap.m_HeightValues);
			m_2DCam.m_vCamPos = m_vDefaultCamPos;
			pDoc->m_b2DNewTerrainGenerated = false;
		}

		// Use Push/Pop to apply camera movement to entire scene

		glPushMatrix();

			// Process camera movement

			m_2DCam.MoveCam();

			// Draw map

			m_MapTexture.Bind();
			SetFilters(GL_LINEAR, GL_LINEAR);
			SetWrap(GL_CLAMP, GL_CLAMP);
			float n = (float)pDoc->m_Heightmap.m_HeightValues.m_pTGAFileHeader->Image.Width;
			glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
				glTexCoord2f(1.0f, 0.0f); glVertex2f(n, 0.0f);
				glTexCoord2f(1.0f, 1.0f); glVertex2f(n, n);
				glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, n);
			glEnd();

		glPopMatrix();
	}
}

void C2DMapView::VirtualOnSize(int width, int height)
{
	// Update member variables

	m_2DCam.m_ViewVol.m_nWndOriginX = 0;
	m_2DCam.m_ViewVol.m_nWndOriginY = 0;
	m_2DCam.m_ViewVol.m_nWndWidth = width;
	m_2DCam.m_ViewVol.m_nWndHeight = height;

	// Call view volume resize function

	m_2DCam.m_ViewVol.OnWindowResize();
}

void C2DMapView::OnSize(UINT nType, int cx, int cy) 
{
	COpenGLView::OnSize(nType, cx, cy);

	m_2DCam.m_vCamPos = m_vDefaultCamPos; // prevents major problems when moving image around...
}

void C2DMapView::OnMenuItemPerlinNoise() 
{
	CPerlinNoiseDlg pndlg(this, GetDocument());
	pndlg.DoModal();
}

void C2DMapView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// Mouse LB is down

	m_bMouseLBDown = true;

	// Store the window space point coordinate

	m_MousePosOnLBClick = point;

	// Change to new cursor

	m_hMouseCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZEALL);
	SetCursor(m_hMouseCursor);

	// Causes all subsequent mouse input to be sent to the current 
	// CWnd object regardless of the position of the cursor. 

	SetCapture(); // remember to release!
}


void C2DMapView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// Mouse LB is up

	m_bMouseLBDown = false;

	// Store the window space point coordinate

	m_MousePosOnLBClick = CPoint(0,0);

	// Restore normal cursor

	m_hMouseCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
	SetCursor(m_hMouseCursor);

	// Other windows can now receive mouse input

	ReleaseCapture();
}

void C2DMapView::OnMouseMove(UINT nFlags, CPoint point) 
{
	// Grab a pointer to the doc

	CTerrainEditorDoc *pDoc = GetDocument();

	// Check various types of operations

	if (pDoc->m_bTerrainDataExists == true)
	{
		if (m_bMouseLBDown) // basic move map operation
		{

			// Create a pixel boundary around heightmap for easier mouse
			// selection and restrict camera movement to keep heightmap always
			// visible...

			float deltax = (float)(point.x - m_MousePosOnLBClick.x);
			float deltay = -(float)(point.y - m_MousePosOnLBClick.y);

			float newCamPosX = m_2DCam.m_vCamPos.x + deltax;
			float newCamPosY = m_2DCam.m_vCamPos.y + deltay;

			float size = (float)pDoc->m_Heightmap.m_HeightValues.m_pTGAFileHeader->Image.Width;

			if (newCamPosX <= m_vDefaultCamPos.x && newCamPosX >= ((float)m_2DCam.m_ViewVol.m_nWndWidth - size - m_vDefaultCamPos.x)) 
				m_2DCam.m_vCamPos.x = newCamPosX;
			if (newCamPosY <= m_vDefaultCamPos.y && newCamPosY >= ((float)m_2DCam.m_ViewVol.m_nWndHeight - size - m_vDefaultCamPos.y))
				m_2DCam.m_vCamPos.y = newCamPosY;

			// Redraw and store new mouse position

			Invalidate(TRUE);
			m_MousePosOnLBClick = point;
		}
	}

	// Display the mouse position in the status pane: mouse position is
	// changed to reflect bottom left as the window origin

	CString sMousePosition;
	sMousePosition.Format("[Heightmap: x=%d/y=%d]", point.x, m_2DCam.m_ViewVol.m_nWndHeight - point.y);
	CTerrainEditorApp *pApp = (CTerrainEditorApp*)AfxGetApp();
	pApp->m_pMainFrame->m_wndStatusBar.SetPaneText(0, sMousePosition, TRUE);
}

void C2DMapView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	// Added here to allow different view classes to change the child window title

	GetParent()->SetWindowText(GetDocument()->GetTitle() + ": 2DMapView");
	Invalidate(TRUE);
}

void C2DMapView::OnInitialUpdate() 
{
	COpenGLView::OnInitialUpdate();
	
	// If user closes 2DMapView and reopens, then show old data

	CTerrainEditorDoc *pDoc = GetDocument();
	pDoc->m_b2DNewTerrainGenerated = true;

	// Keep a pixel gap around window edge for better viewing

	m_2DCam.m_vCamPos = m_vDefaultCamPos;
	Invalidate(TRUE);
}

void C2DMapView::OnMenuItemOpenGLInfo() 
{
	COpenGLInfoDlg ogldlg;
	ogldlg.m_Company = "Company: " + m_extOpenGL.m_strCompany;
	ogldlg.m_Renderer = "Renderer: " + m_extOpenGL.m_strRenderer;
	ogldlg.m_Version = "Version: " + m_extOpenGL.m_strVersion;
	ogldlg.m_strExtensions = m_extOpenGL.m_strExtensions;
	ogldlg.m_strWGLExtensions = m_extOpenGL.m_strWGLExtensions;
	ogldlg.DoModal();
}
